#include "tcpserver.hpp"
#include "socket.hpp"
#include "util.hpp"
#include <unordered_map>

static const std::string linespace = "\r\n";
static const std::string space = " ";
static const std::string requestsep = ": ";

static const std::string webroot = "./wwwroot";
static const std::string indexfile = "/index.html";
static const std::string errfile = "/404.html";
class HttpRequest
{
public:
    HttpRequest() : _spaceline(linespace)
    {
    }
    ~HttpRequest() {}
    // 序列化
    std::string Serialize()
    {
        return std::string();
    }
    void ParseReqLine(std::string &line)
    {
        std::stringstream ss(line);
        ss >> _method >> _uri >> _version;
    }
    // 反序列化
    bool Deserialize(std::string &buff)
    {
        // 提取请求行
        auto pos = buff.find(linespace);
        if (pos == std::string::npos)
            return false;
        std::string req_line = buff.substr(0, pos);
        buff.erase(0, pos);
        // 解析请求行
        ParseReqLine(req_line);
        LOG(Level::DEBUG) << "_method : " << _method;
        LOG(Level::DEBUG) << "_uri : " << _uri;
        LOG(Level::DEBUG) << "_version : " << _version;
        // 解析uri
        if (_uri == "/")
            _uri = webroot + indexfile;
        else
            _uri = webroot + _uri;
        return true;
    }
    std::string Uri() { return _uri; }

private:
    std::string _method;  // 请求方法
    std::string _uri;     // URI
    std::string _version; // HTTP版本

    std::unordered_map<std::string, std::string> _headers; // 请求报头
    std::string _spaceline;                                // 空行
    std::string _text;                                     // 正文
};

class HttpResponce
{
public:
    HttpResponce(const std::string &desig)
        : _version("HTTP/1.1"),
          _spaceline(linespace),
          _targetfile(desig)
    {
    }
    ~HttpResponce() {}
    std::string Serialize()
    {
        std::string state_line = _version + space + std::to_string(_code) + space + _desc + linespace;
        std::string head_line;
        for (auto &e : _headers)
        {
            head_line += e.first + requestsep + e.second;
        }
        return state_line + head_line + _spaceline + _text;
    }
    void SetCode(int code)
    {
        _code = code;
        switch (_code)
        {
        case 404:
            _desc = "not found";
            break;
        case 200:
            _desc = "OK";
            break;
        default:
            break;
        }
    }
    void AddHeader(const std::string &key, const std::string &value)
    {
        auto pos = _headers.find(key);
        if (pos != _headers.end()) // 当前已经存在key字段
            return;
        _headers.insert(std::make_pair(key, value));
    }
    std::string GetFileExte(const std::string &filename)
    {
        auto pos = filename.rfind(".");
        if (pos == std::string::npos)
            return "text/html";
        std::string exte = filename.substr(pos);
        if (exte == ".html" || exte == ".htm")
            return "text/html";
        else if (exte == ".jpg")
            return "image/jpeg";
        else if (exte == ".png")
            return "image/png";
        else
            return "text/html";
    }
    bool MakeResponce()
    {
        if (_targetfile == "./wwwroot/favicon.ico")
        {
            LOG(Level::DEBUG) << "client get : " << _targetfile << ", 忽略";
            return false;
        }
        int filesize = 0;
        bool i = Util::ReadFile(_targetfile, &_text);
        if (!i)
        {
            LOG(Level::DEBUG) << "client get : " << _targetfile << ", but not found";
            SetCode(404);
            // 失败,返回404页面
            std::string filename = webroot + errfile;
            Util::ReadFile(filename, &_text);
            filesize = Util::FileSize(filename);
            std::string exte = GetFileExte(filename);
            // AddHeader("Content-Type", exte);
        }
        else
        {
            SetCode(200);
            filesize = Util::FileSize(_targetfile);
            std::string exte = GetFileExte(_targetfile);
            // AddHeader("Content-Type", exte);
        }
        // AddHeader("Content-Length", std::to_string(filesize));
        return true;
    }

public:
    std::string _version; // HTTP 版本
    int _code;            // 状态码
    std::string _desc;    // 状态码描述

    std::unordered_map<std::string, std::string> _headers; // 响应报头
    std::string _spaceline;                                // 空行
    std::string _text;                                     // 正文

    std::string _targetfile; // 指定文件
};
class Http
{
public:
    Http() {}
    Http(int port) : _tsvrp(std::make_unique<TcpServer>(port))
    {
    }
    ~Http() {}
    void HandlerRuquest(std::shared_ptr<Socket> sock, InetAddr &client)
    {
        std::string buff;
        sock->Recv(buff);
        // 读取报文的完整性 err
        std::cout << buff << std::endl;
        // 读取到完整报文
        HttpRequest req;
        req.Deserialize(buff);

        // 响应
        LOG(Level::DEBUG) << "-----Client Request-----" << req.Uri();
        HttpResponce res(req.Uri());
        if (res.MakeResponce())
        {
            std::string send_res = res.Serialize();
            sock->Send(send_res);
        }
        // 传输指定文件

        // 传输固定文件
        // // 从文件中读取
        // std::string filepath = webroot + '/' + filename;
        // LOG(Level::DEBUG) << "-----用户请求-----" << filepath;
        // Util::ReadFile(filepath, &res._text);
        // std::string send_res = res.Serialize();
        // sock->Send(send_res);
    }
    void Start()
    {
        _tsvrp->Start([this](std::shared_ptr<Socket> sock, InetAddr &client)
                      { this->HandlerRuquest(sock, client); });
    }

private:
    std::unique_ptr<TcpServer> _tsvrp;
};